package com.quick.develop.business.service.impl;

import com.quick.develop.business.service.BusinessService;
import com.quick.develop.business.vo.BusinessProcessVO;
import com.quick.develop.flowable.application.IBpmProcessInstanceApplication;
import com.quick.develop.flowable.application.IBpmTaskApplication;
import com.quick.develop.flowable.convert.process.BpmProcessReqVoConvert;
import com.quick.develop.flowable.domain.vo.draft.BpmDraftReqVO;
import com.quick.develop.flowable.domain.vo.instance.BpmProcessInstanceCreateReqVO;
import com.quick.develop.flowable.domain.vo.process.BpmProcessReqVO;
import com.quick.develop.flowable.domain.vo.task.BpmTaskRejectReqVO;
import com.quick.develop.flowable.domain.vo.task.BpmTaskReqVO;
import com.quick.develop.flowable.domain.vo.task.BpmTaskUpdateAssigneeReqVO;
import com.quick.develop.flowable.enums.BpmExecuteCmd;
import com.quick.develop.flowable.service.task.IBpmDraftService;
import com.quick.develop.form.application.FormApplication;
import com.quick.develop.framework.common.exception.ServerException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

@AllArgsConstructor
@Component
@Slf4j
public class BusinessServiceImpl implements BusinessService {

    private final IBpmTaskApplication taskApplication;
    private final IBpmProcessInstanceApplication processInstanceApplication;
    private final IBpmDraftService draftService;
    private final FormApplication formApplication;

    @Override
    public void handle(BusinessProcessVO formInstance) {
        BpmProcessReqVO bpmReqVo = formInstance.getProcess();
        if (Objects.isNull(bpmReqVo)) {
            throw new ServerException("流程参数不能为空!" );
        }
        Map<String, Object> vars = formInstance.getVars();
        bpmReqVo.setBusinessKey(formInstance.getBusinessKey());
        bpmReqVo.setProcessVariables(vars);
        log.info("任务处理类型：{}", bpmReqVo.getExecuteCmd());
        BpmExecuteCmd exCmd = BpmExecuteCmd.getBpmExecute(bpmReqVo.getExecuteCmd());
        if (Objects.nonNull(exCmd)) {
            switch (exCmd) {
                case SAVE:
                    this.saveProcess(bpmReqVo, formInstance);
                    break;
                case SUBMIT:
                    this.submitProcess(bpmReqVo, formInstance);
                    break;
                case APPROVE:
                case READ:
                case AGREE:
                case DISAGREE:
                    this.completeTask(bpmReqVo, formInstance);
                    break;
                case BACK:
                    this.rollbackTask(bpmReqVo, formInstance);
                    break;
                case DELEGATE:
                    this.delegateTask(bpmReqVo, formInstance);
                    break;
                case ASSIGN:
                    this.assignTask(bpmReqVo, formInstance);
                    break;
                case CLAIM:
                    this.claimTask(bpmReqVo);
                    break;
                case UN_CLAIM:
                    this.unClaimTask(bpmReqVo);
                    break;
                case STOP:
                    this.stopTask(bpmReqVo, formInstance);
                    break;
                case WITHDRAW:
                    this.withdrawTask(bpmReqVo);
                    break;
                case DRAFT_DELETE:
                    this.deleteDraft(bpmReqVo, formInstance);
                    break;
                default:
                    break;
            }
        }
    }

    public void saveProcess(BpmProcessReqVO bpmReqVo, BusinessProcessVO formInstance) {
        handleBusinessData(formInstance);
        if (Objects.isNull(bpmReqVo.getDraftId()) && StringUtils.isEmpty(bpmReqVo.getProcessInstanceId())) {
            BpmDraftReqVO bpmDraftReqVO = BpmProcessReqVoConvert.INSTANCE.convert4(bpmReqVo);
            draftService.addDraft(bpmDraftReqVO);
        }
    }

    public void submitProcess(BpmProcessReqVO bpmReqVo, BusinessProcessVO formInstance) {
        if (StringUtils.isEmpty(bpmReqVo.getProcessInstanceId())) {
            this.startProcess(bpmReqVo, formInstance);
        } else {
            this.completeTask(bpmReqVo, formInstance);
        }
    }

    public void startProcess(BpmProcessReqVO bpmReqVo, BusinessProcessVO formInstance) {
        // 设置当前登录人信息
        this.setFillInfo(formInstance);
        //业务数据处理
        handleBusinessData(formInstance);
        BpmProcessInstanceCreateReqVO createReqVO = BpmProcessReqVoConvert.INSTANCE.convert(bpmReqVo);
        processInstanceApplication.startProcess(createReqVO);
        //考虑是否存在草稿  删除草稿
        Optional.ofNullable(bpmReqVo.getDraftId()).ifPresent(this::deleteDraftEx);
    }

    public void completeTask(BpmProcessReqVO reqVO, BusinessProcessVO formInstance) {
        //业务数据处理
        handleBusinessData(formInstance);

        //流程任务完成
        BpmTaskReqVO taskReqVO = BpmProcessReqVoConvert.INSTANCE.convert1(reqVO);
        taskApplication.complete(taskReqVO);
    }

    public void assignTask(BpmProcessReqVO reqVO, BusinessProcessVO formInstance) {
        //业务数据处理
        handleBusinessData(formInstance);

        BpmTaskUpdateAssigneeReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert2(reqVO);
        taskApplication.assignTask(vo);
    }

    public void rollbackTask(BpmProcessReqVO reqVO, BusinessProcessVO formInstance) {
        //业务数据处理
        handleBusinessData(formInstance);

        BpmTaskRejectReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert3(reqVO);
        taskApplication.rollbackTaskByTaskId(vo);
    }

    public void delegateTask(BpmProcessReqVO reqVO, BusinessProcessVO formInstance) {
        //业务数据处理
        handleBusinessData(formInstance);

        BpmTaskUpdateAssigneeReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert2(reqVO);
        taskApplication.delegate(vo);
    }

    public void claimTask(BpmProcessReqVO reqVO) {
        BpmTaskReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert1(reqVO);
        taskApplication.claim(vo);
    }

    public void unClaimTask(BpmProcessReqVO reqVO) {
        BpmTaskReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert1(reqVO);
        taskApplication.unClaim(vo);
    }

    public void stopTask(BpmProcessReqVO reqVO, BusinessProcessVO formInstance) {
        //业务数据处理
        handleBusinessData(formInstance);
        BpmTaskReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert1(reqVO);
        taskApplication.stopTask(vo);
    }

    public void withdrawTask(BpmProcessReqVO reqVO) {

        BpmTaskReqVO vo = BpmProcessReqVoConvert.INSTANCE.convert1(reqVO);
        taskApplication.withdrawTask(vo);
    }

    public void deleteDraft(BpmProcessReqVO reqVO, BusinessProcessVO formInstance) {
        this.deleteBusinessData(formInstance);
        this.deleteDraftEx(reqVO.getDraftId());
    }

    public void handleBusinessData(BusinessProcessVO formInstance) {
        formApplication.executeFormBusiness(formInstance);
    }

    public void deleteBusinessData(BusinessProcessVO formInstance) {

    }

    public void setFillInfo(BusinessProcessVO businessProcessVO) {

    }

    public void deleteDraftEx(Long draftId) {
        draftService.deleteDraftById(draftId);
    }
}
